package fileService;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;

import connectionService.ConnectionServiceAndroidClient;

import entities.Device;

import android.util.Log;
import androidApplication.Commons;
import androidApplication.FileIO;

public class FileServiceHost implements Serializable{
	private SSLServerSocket messageService;
	
	public FileServiceHost(){
		
	}

	public void handleRequest(SSLSocket client, FileIO fileIO, ConnectionServiceAndroidClient csClient, Device thisDevice){
		Log.i("FileServiceHost","HandleRequest()");
		try{
			InputStreamReader isr = new InputStreamReader(client.getInputStream());
			BufferedReader in = new BufferedReader(isr);
			
			OutputStreamWriter osw = new OutputStreamWriter(client.getOutputStream());
			BufferedWriter out = new BufferedWriter(osw); 
	
			String methodName = "";
			if((methodName = in.readLine()) != null){
				if(methodName.equalsIgnoreCase("getfilenames")){
					out.write("arlistart");
					out.write("\n");
					out.flush();
					for(String s : getFileNames(fileIO)){
						out.write(s);
						out.write("\n");
						out.flush();
					}
					out.write("arliend");
					out.write("\n");
					out.flush();
	
					String received = in.readLine();
					if(received.equalsIgnoreCase("received")){
						Log.i("FSH: GetFileNames", "Done");
					}else{
						Log.e("FileServiceHost", "Invalid Message: " + received);
					}
				}else if(methodName.equalsIgnoreCase("getdevice")){
					Device d = getDevice(csClient, thisDevice);
					
					out.write("devicestart");
					out.write("\n");
					out.flush();
					
					String device = "Name:"+d.getDeviceName()+
							";IP:"+d.getIpAddress()+
							";UUID:"+d.getUUID()+
							";Type:"+d.getDeviceType();
					
					out.write(device);
					out.write("\n");
					out.flush();
					
					if(d.getConnectedDevices().size() > 1){
						out.write("arlistart");
						out.write("\n");
						out.flush();
						for(String connection : d.getConnectedDevices()){
							out.write(connection);
							out.write("\n");
							out.flush();
						}
						out.write("arliend");
						out.write("\n");
						out.flush();
					}
					out.write("deviceend");
					out.write("\n");
					out.flush();
					
					String recieved = in.readLine();
				}else if(methodName.equalsIgnoreCase("sendfile")){//writes to disk
					out.write("sendfilename");
					out.write("\n");
					out.flush();
					String fileName = in.readLine();
					
					String startFileService = in.readLine();
					FileReceiverService fs = new FileReceiverService();
					if(startFileService.equalsIgnoreCase("startfileservice")){
						fs.startReceiveFileService();
					
						out.write("fileservicestarted");
						out.write("\n");
						out.flush();
						
						out.write("sendfilesize");
						out.write("\n");
						out.flush();
						
						String fileSizeString = in.readLine();
						int fileSize = Integer.parseInt(fileSizeString);
							SSLSocket clientFile = fs.receiveFileConnection();
							CSFileWrapper file = fs.receiveFile(clientFile, fileName, fileSize);
							fs.stopReceiveFileService();
							
						out.write("filereceived");
						out.write("\n");
						out.flush();
						
						sendFile(file, fileIO);
					}
				}else if(methodName.equalsIgnoreCase("getfile")){//send file to client
					out.write("sendfilename");
					out.write("\n");
					out.flush();
					String fileName = in.readLine();
					CSFileWrapper file = getFile(fileName, fileIO);

					out.write("startfileservice");
					out.write("\n");
					out.flush();
					String serviceStarted = in.readLine();
					if(serviceStarted.equalsIgnoreCase("fileservicestarted")){
						String fileSize = in.readLine();
						if(fileSize.equalsIgnoreCase("sendfilesize")){
							fileSize = String.valueOf(file.getData().length);
							out.write(fileSize);
							out.write("\n");
							out.flush();
							
							FileReceiverService fs = new FileReceiverService();
							try{
								fs.sendFile(file.getData(), client.getInetAddress());
							}catch(UnknownHostException e){e.printStackTrace();}
						}else{
							Log.e("FileServiceHost","Invalid Message: " + fileSize);
						}
					}else{
						Log.e("FileServiceHost", "Invalid Message: " + serviceStarted);
					}
					
					String fileReceived = in.readLine();
					if(fileReceived != null){
						if(fileReceived.equalsIgnoreCase("received")){
							Log.i("FileServiceHost", "Finished");
						}else{
							Log.e("FileServiceHost", "Invalid Message: " + fileReceived);
						}
					}else{
						Log.i("FileServiceHost", "Received null");
					}
				}else{
					out.write("Invalid Request");
					out.write("\n");
					out.flush();
				}
				in.close();
				out.close();
				client.close();
			}
		}catch(IOException e){e.printStackTrace();}
	}
	
	public ArrayList<String> getFileNames(FileIO fileIO){
		Log.i("FileServiceHost","getFileNames()");
		return fileIO.getFileNames();
	}
	public CSFileWrapper getFile(String fileName, FileIO fileIO){
		Log.i("FileServiceHost","getFile()");
		return fileIO.getFile(fileName);
	}
	public void sendFile(CSFileWrapper file, FileIO fileIO){
		Log.i("FileServiceHost","sendFile()");
		fileIO.writeFile(file.getFileName(), file.getData());
	}
	public Device getDevice(ConnectionServiceAndroidClient csClient, Device thisDevice){
		Log.i("FileServiceHost","getDevice()");
		return csClient.getDevice(thisDevice.getUUID(), false);
	}
	
	//MessageService	
	public void startService() throws IOException{
		Log.i("FileServiceHost","startService()");
		SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
		messageService = (SSLServerSocket) factory.createServerSocket(2081);
		messageService.setEnabledCipherSuites(messageService.getSupportedCipherSuites());
//		messageService = new ServerSocket(2081);
	}
	public void stopService() throws IOException{
		Log.i("FileServiceHost","stopService()");
		messageService.close();
	}
	public SSLSocket receiveMessageConnection() throws IOException{
		Log.i("FileServiceHost","receiveMessageConnection()");
		SSLSocket client = (SSLSocket) messageService.accept();
		return client;
	}
	
	public SSLServerSocket getMessageService(){
		return messageService;
	}
	
	public void setMessageService(SSLServerSocket messageService){
		this.messageService = messageService;
	}
}
